#include "Nano100Series.h"
#include "ProximitySensor.h"
#include "Common.h"
#include "I2c1.h"

#define EM30718_I2C_ADDR				(0x48 >> 1)
#define EM30718_PID						(0x31)

#define EM30718_REG_ADDR_PID			(0x00)
#define EM30718_REG_ADDR_CONFIG			(0x01)
#define EM30718_REG_ADDR_INTERRUPT		(0x02)
#define EM30718_REG_ADDR_PS_LT			(0x03)
#define EM30718_REG_ADDR_PS_HT			(0x04)
#define EM30718_REG_ADDR_ALSIR_TH1		(0x05)
#define EM30718_REG_ADDR_ALSIR_TH2		(0x06)
#define EM30718_REG_ADDR_ALSIR_TH3		(0x07)
#define EM30718_REG_ADDR_PS_DATA		(0x08)
#define EM30718_REG_ADDR_ALSIR_DATA1	(0x09)
#define EM30718_REG_ADDR_ALSIR_DATA2	(0x0A)
#define EM30718_REG_ADDR_TEST1			(0x0E)
#define EM30718_REG_ADDR_TEST2			(0x0F)

// without glass cover
//#define EM30718_PS_LT					(10)
//#define EM30718_PS_HT					(50)

// with glass cover
#define EM30718_PS_LT					(5)
#define EM30718_PS_HT					(15)

static int is_em30718_exist = 0;
static enum proximity_sensor_state_t proximity_sensor_state = PROXIMITY_SENSOR_STATE_CLOSE;

static int ProximitySensorWrite8(uint8_t reg_addr, uint8_t reg_val)
{
	struct i2c_msg_t i2c_msg;
	int ret;
	uint8_t buf[2];

	buf[0] = reg_addr;
	buf[1] = reg_val;

	i2c_msg.addr = EM30718_I2C_ADDR;
	i2c_msg.tx_buf = buf;
	i2c_msg.tx_to_write = 2;
	i2c_msg.tx_write = 0;
	i2c_msg.rx_buf = NULL;
	i2c_msg.rx_to_read = 0;
	i2c_msg.rx_read = 0;

	ret = I2c1XferAlt(&i2c_msg);
	if (ret < 0) {
		return 0;
	} else {
		return i2c_msg.tx_write;
	}
}

static int ProximitySensorRead8(uint8_t reg_addr, uint8_t *reg_val)
{
	struct i2c_msg_t i2c_msg;
	int ret;
	uint8_t buf[1];

	buf[0] = reg_addr;

	i2c_msg.addr = EM30718_I2C_ADDR;
	i2c_msg.tx_buf = buf;
	i2c_msg.tx_to_write = 1;
	i2c_msg.tx_write = 0;
	i2c_msg.rx_buf = reg_val;
	i2c_msg.rx_to_read = 1;
	i2c_msg.rx_read = 0;

	ret = I2c1XferAlt(&i2c_msg);
	if (ret < 0) {
		return 0;
	} else {
		return i2c_msg.rx_read;
	}
}

void ProximitySensorInit(void)
{
	uint8_t reg_val;
	int ret;

	reg_val = 0;
	ret = ProximitySensorRead8(EM30718_REG_ADDR_PID, &reg_val);
	if ((ret == 0) || (reg_val != EM30718_PID)) {
		is_em30718_exist = 0;
		LogDebug("can not find proximity sensor em30718\n");
	} else {
		is_em30718_exist = 1;
		LogDebug("proximity sensor id : 0x%02X\n", reg_val);
	}

	ProximitySensorWrite8(EM30718_REG_ADDR_CONFIG, 0);
	ProximitySensorWrite8(EM30718_REG_ADDR_INTERRUPT, 0);
	ProximitySensorWrite8(EM30718_REG_ADDR_PS_LT, EM30718_PS_LT);
	ProximitySensorWrite8(EM30718_REG_ADDR_PS_HT, EM30718_PS_HT);
	ProximitySensorWrite8(EM30718_REG_ADDR_CONFIG,
							(1 << 7) | (1 << 6) | (1 << 3));
}

void ProximitySensorUpdateState(void)
{
	uint8_t reg_val;
	int ret;

	if (!is_em30718_exist) {
		proximity_sensor_state = PROXIMITY_SENSOR_STATE_CLOSE;
	}
	ret = ProximitySensorRead8(EM30718_REG_ADDR_PS_DATA, &reg_val);
	//LogDebug("EM30718_REG_PS_DATA : %u, ret : %d\n", reg_val, ret);
	if (ret == 0) {
		proximity_sensor_state = PROXIMITY_SENSOR_STATE_CLOSE;
	} else {
		if (reg_val >= EM30718_PS_HT) {
			proximity_sensor_state = PROXIMITY_SENSOR_STATE_CLOSE;
		} else if (reg_val <= EM30718_PS_LT) {
			proximity_sensor_state = PROXIMITY_SENSOR_STATE_LEAVE;
		}
	}
}

enum proximity_sensor_state_t ProximitySensorGetState(void)
{
	return proximity_sensor_state;
}
